using System.Collections.Generic;
using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;

namespace IQIGame.Onigao.Logic
{
    public class SkillComponent : TComponent
    {
        public BattleUpdateResultContrller resultCtrl;

        public List<Skill> skills = new List<Skill>();
        public Dictionary<int, Skill> skillDict = new Dictionary<int, Skill>();

        private Unit unit;

        /// <summary>
        /// 触发技能的次数, 注意此处仅有有次数限制的数据
        /// </summary>
        private Dictionary<int, SkillExecuteData> mTriggerData = new Dictionary<int, SkillExecuteData>();

        class SkillExecuteData
        {
            public Skill skill;
            public int maxTurnCount;
            public int curTurnCount;
            public int maxSkillCount;
            public int curSkillCount;
            public int maxRoundCount;
            public int curRoundCount;
        }

        protected override void OnDispose()
        {
        }

        public override void OnCreate(TEntity entity)
        {
            this.unit = entity as Unit;
        }

        public void Initialize(Dictionary<int, int> skills)
        {
            var rList = new List<(int, (SkillConfig, int))>();
            foreach (var rPair in skills)
            {
                var nID = rPair.Key;
                var rConfig = SkillFactory.GetConfig(nID);
                if (rConfig != null)
                {
                    rList.Add((nID, (rConfig, rPair.Value)));
                }
            }

            for (int i = 0; i < rList.Count; i++)
            {
                var rItem = rList[i];
                var rSkill = SkillFactory.CreateSkill(rItem.Item1, rItem.Item2.Item1, rItem.Item2.Item2, this.unit);
                this.AddSkill(rSkill, true);
            }
        }

        public void OnEnable()
        {
            for (int i = 0; i < this.skills.Count; i++)
            {
                this.skills[i].Enable();
            }
        }

        public bool AddSkill(Skill skill, bool init = false)
        {
            if (skill == null)
            {
                return false;
            }

            if (!this.skillDict.TryAdd(skill.skillID, skill))
            {
                return false;
            }

            skill.executer = this.unit;
            this.skills.Add(skill);
            if (skill.config.MaxTurnCount > 0 || skill.config.MaxSkillCount > 0 || skill.config.MaxRoundCount > 0)
            {
                var rData = new SkillExecuteData()
                {
                    skill = skill,
                    maxTurnCount = skill.config.MaxTurnCount,
                    maxSkillCount = skill.config.MaxSkillCount,
                    maxRoundCount = skill.config.MaxRoundCount,
                    curTurnCount = 0,
                    curSkillCount = 0,
                    curRoundCount = 0,
                };
                this.mTriggerData.Add(skill.skillID, rData);
            }

            if (!init)
            {
                if (this.resultCtrl == null)
                {
                    this.resultCtrl = this.unit.battle.playCtrl.resultCtrl;
                }

                var rPOD = BattleUpdateFactory.CreateAddSkill(this.unit.GUID, true, skill.skillID);
                this.resultCtrl.Add(rPOD);

                skill.Enable();
            }
            return true;
        }

        public bool TryGetSkill(int skillID, out Skill skill)
        {
            // 如果是-1表示宠物技能
            if (skillID == -1)
            {
                var rPetComp = this.unit.GetComponent<PetComponent>(ETComponentType.PetComponent);
                skillID = rPetComp.petSkill;
            }
            return this.skillDict.TryGetValue(skillID, out skill);
        }

        public void EnableSkill(int nSkillID)
        {
            this.skills.Find((x) => x.skillID == nSkillID)?.Enable();
        }

        public void DisableSkill(int nSkillID)
        {
            this.skills.Find((x) => x.skillID == nSkillID)?.Disable();
        }

        public void RemoveSkill(Skill rSkill)
        {
            if (rSkill == null)
            {
                return;
            }

            if (this.resultCtrl == null)
            {
                this.resultCtrl = this.unit.battle.playCtrl.resultCtrl;
            }
            // 用来保证不会重复移除
            if (this.skillDict.Remove(rSkill.skillID))
            {
                var rPOD = BattleUpdateFactory.CreateAddSkill(this.unit.GUID, false, rSkill.skillID);
                this.resultCtrl.Add(rPOD);

                if (rSkill.executing > 0)
                {
                    rSkill.RemoveSign = true;
                }
                else
                {
                    rSkill.Dispose();
                }

                this.skills.Remove(rSkill);
                this.mTriggerData.Remove(rSkill.skillID);
            }
        }

        public bool OnTrigger(int nSkillID)
        {
            if (this.mTriggerData.TryGetValue(nSkillID, out var rData))
            {
                ++rData.curTurnCount;
                ++rData.curSkillCount;
                ++rData.curRoundCount;
                return (rData.maxTurnCount <= 0 || rData.curTurnCount <= rData.maxTurnCount) &&
                       (rData.maxSkillCount <= 0 || rData.curSkillCount <= rData.maxSkillCount) &&
                       (rData.maxRoundCount <= 0 || rData.curRoundCount <= rData.maxRoundCount);
            }

            return true;
        }

        public void OnRoundStart()
        {
            foreach (var rPair in this.mTriggerData)
            {
                rPair.Value.curRoundCount = 0;
            }

            for (int i = 0; i < this.skills.Count; i++)
            {
                var rSkill = this.skills[i];
                if (rSkill.curCd > 0)
                {
                    rSkill.curCd--;
                }
            }
        }

        public void OnTurnStart()
        {
            foreach (var rPair in this.mTriggerData)
            {
                rPair.Value.curTurnCount = 0;
            }
        }

        public void OnTurnSkillStart()
        {
            foreach (var rPair in this.mTriggerData)
            {
                rPair.Value.curSkillCount = 0;
            }
        }

        public void OnDead()
        {
            for (int i = 0; i < this.skills.Count; i++)
            {
                var rSkill = this.skills[i];
                rSkill.Disable();
            }
        }

        public void Relive()
        {
            for (int i = 0; i < this.skills.Count; i++)
            {
                var rSkill = this.skills[i];
                rSkill.Enable();
            }
        }
    }
}